import React, {memo, useEffect, useState} from 'react';
import {message, Modal, Progress} from "antd";

import "./run.css";
import "../../../components/pageNavigation/index.css";
import Header from "../../../components/main-header/Header";
import {calcTime, deepClone, getCurrentDay, getCurrentHours, getCurrentMinutes, getCurrentMonth, getCurrentYear, sortByProperty} from "../../../common/utils";
import {useDispatch, useSelector} from "react-redux";
import {
  saveCurrentTempData,
  saveMeltData,
  saveOpenBell,
  savePauseCacheTime,
  savePcrData,
  saveRemainTime,
  saveRunExperimentName,
  saveRunPercent,
  saveRunTime,
  saveStartTime,
  saveStartTimeStamp,
  saveStopTime
} from "./store/actionCreators";
import request from "../../../services/request";
import ExperimentName from "../../../components/experimentName/ExperimentName";
import RealtimeCurve from "./components/realtimeCurve/RealtimeCurve";
import Status from "./components/status/Status";
import bell from "./images/bell.png";
import bellX from "./images/bellX.png";
import {STATUS_PAUSE, STATUS_WORK} from "./config";
import {saveData} from "../store/actionCreators";
import {saveJump2Run} from "../protocol/store/actionCreators";
import {LINE_OBJ} from "../plate/config";
import {saveExportObj, saveExportObjCn} from "../export/store/actionCreators";
import {saveMultiData} from "../analysis/store/actionCreators";
import {useChangeCoordinate} from "../../../common/myHooks";
import {Link} from "react-router-dom";
import {AMPLIFICATION, HOLD, INFINITE_HOLD, MELT} from "../protocol/config";

export default memo(function Run() {
  const [navIndex, setNavIndex] = useState(0);  //  导航点击索引
  const [toggleTime, setToggleTime] = useState(true);  //  切换运行时间/剩余时间
  const [stopMention, setStopMention] = useState(false); //  stop提示框
  const [pauseMention, setPauseMention] = useState(false); //  pause提示框
  const [restartMention, setRestartMention] = useState(false); //  restart提示框
  const navContent = [
    {content: "Status", path: "/main/run"},
    {content: "Realtime Curve", path: "/main/run/realtimeCurve"}];
  const navContent_CN = [
    {content: "状态", path: "/main/run"},
    {content: "实时曲线", path: "/main/run/realtimeCurve"}];
  const dispatch = useDispatch();
  const {
    data,
    pauseCacheTime,
    startTimeStamp,
    startTime,
    stopTime,
    runPercent,
    runTime,
    remainTime,
    isJump2Run,
    openBell,
    runStart,
    runExperimentName,
    exportObj,
    exportObjCn,
    multiData,
    isCN
  } = useSelector(state => ({
    data: state.dataReducer.data,
    startTime: state.runReducer.startTime,
    stopTime: state.runReducer.stopTime,
    runPercent: state.runReducer.runPercent,
    runTime: state.runReducer.runTime,
    remainTime: state.runReducer.remainTime,
    isJump2Run: state.protocolReducer.isJump2Run,
    openBell: state.runReducer.openBell,
    runStart: state.runReducer.runStart,
    runExperimentName: state.runReducer.runExperimentName,//  start后保存当前运行的实验名,用于和下一次start时进行比较,判断是否需要重命名
    startTimeStamp: state.runReducer.startTimeStamp,//  开始实验的时间戳
    pauseCacheTime: state.runReducer.pauseCacheTime, //  暂停时缓存运行时间
    exportObj: state.exportReducer.exportObj,
    exportObjCn: state.exportReducer.exportObjCn,
    multiData: state.analysisReducer.multiData,
    isCN: state.languageReducer.isCN
  }));
  const changeCoordinate = useChangeCoordinate();
  let cloneDataWells = [];
  let cloneDataWells_ = [];
  let cloneMultiData = [];

  useEffect(() => {
    let runTimeDom = document.getElementById("runTimeTop");
    let timer = setInterval(() => {
      runTimeDom.innerText = getCurrentHours() + ":" + getCurrentMinutes();
    }, 1000);
    return () => clearInterval(timer);
  }, []);

  useEffect(() => {
    isJump2Run && start();  //  从protocol跳转过来直接开始实验
  }, [isJump2Run]);

  //  开始实验
  function start() {
    changeCoordinate(data);
    if (runStart) {
      return message.warn("Experiment is starting.");
    }
    if (data.experimentName === runExperimentName) {
      return message.warn("Please change the experiment name.");
    }
    dispatch(saveJump2Run(false));
    cloneDataWells = deepClone(data.wells, cloneDataWells);
    cloneDataWells_ = deepClone(data.wells, cloneDataWells_);
    cloneDataWells.forEach(well => {
      well.lines = [{...LINE_OBJ}, {...LINE_OBJ}, {...LINE_OBJ}, {...LINE_OBJ}, {...LINE_OBJ}, {...LINE_OBJ}];
      well.meltData = [];
      well.meltPeak = [];
      well.targets.forEach(target => [target.b, target.e, target.k, target.r2] = [-1, -1, -1, -1]);
    }); //  每次运行仪器前初始化部分参数
    //TODO:标准曲线参数初始化需以plate界面设置为准
    cloneDataWells.forEach((well, index) => {
      well.lines.forEach((item, it) => {
        item.sq = Number(cloneDataWells_[index].lines[it].sq);
      });
    });

    let cloneStages = [];
    cloneStages = deepClone(data.protocol.stages, cloneStages);
    let stages_ = updateProtocolHold(cloneStages);
    console.log(stages_);
    dispatch(saveData({...data, wells: cloneDataWells}));
    //  设置Export对象
    let cloneExportObj = {};
    cloneExportObj = deepClone(isCN ? exportObjCn : exportObj, cloneExportObj);
    cloneExportObj.run.runTime = `${getCurrentMonth()} ${getCurrentDay()}, ${getCurrentYear()}`;
    isCN ? dispatch(saveExportObjCn(cloneExportObj))
      : dispatch(saveExportObj(cloneExportObj));

    request({
      url: 'deviceAction/start',
      data: {
        ...data,
        wells: cloneDataWells,
        protocol: {
          ...data.protocol,
          stages: stages_
        }
      },
      method: 'post'
    }).then(res => {
      switch (res.code) {
        case 200:
          let cloneMultiData = [...multiData];
          cloneMultiData[0] = {...data, wells: cloneDataWells};
          dispatch(saveMultiData(cloneMultiData));  //  将多实验中的当前实验设置为点击开始时的状态
          dispatch(saveStartTime(`${getCurrentHours()}:${getCurrentMinutes()}`));
          dispatch(saveStopTime(""));
          dispatch(saveStartTimeStamp(Date.now()));
          dispatch(saveRunPercent(0)); //  初始化运行进度条
          dispatch(saveRemainTime(calcTime(0)));  //  初始化剩余时间
          dispatch(saveRunTime(calcTime(0))); //  初始化运行时间
          dispatch(saveCurrentTempData([]));  //  初始化温度数据
          dispatch(savePcrData({
            channel1: [],
            channel2: [],
            channel3: [],
            channel4: [],
            channel5: [],
            channel6: []
          }));  //  初始化melt数据
          dispatch(saveMeltData([]));  //  初始化pcr数据
          dispatch(saveRunExperimentName(data.experimentName));
          break;
        case 500:
          isCN
            ? message.error("仪器未连接或实验名称重复")
            : message.error("Instrument not connected or experiment name duplicated");
          break;
        default:
          isCN
            ? message.error("")
            : message.error("Network request is in progress, please wait a while and try again");
          // TODO: 排查错误
          console.log("上一个网络请求还未结束");
      }
    }).catch(err => message.error(err));
  }

  //  停止实验
  function stop() {
    request({
      url: 'deviceAction/getStatus',
      data: data.connectPort,
      method: 'post',
      forbiddenLogo: true
    })
      .then(res => res.workStatus !== STATUS_WORK
        ?
        isCN
          ? message.warn("实验没有运行！")
          : message.warn("Experiment not run！")
        : setStopMention(true))
      .catch(err => message.error(err));
  }

  //  强制停止
  function forceStop() {
    setStopMention(false);
    request({
      url: 'deviceAction/stop',
      data: {
        connectPort: data.connectPort,
        force: true
      },
      method: 'post'
    }).then(res => {
      switch (res.code) {
        case 200:
          dispatch(saveStopTime(`${getCurrentHours()}:${getCurrentMinutes()}`));
          dispatch(savePauseCacheTime(0));
          break;
        case 500:
          message.error(res.message);
          break;
        default:
          message.error("error");
          // TODO: 排查错误
          console.log(res);
      }
    }).catch(err => message.error(err));
  }

  //  暂停实验
  function Pause() {
    request({
      url: 'deviceAction/getStatus',
      data: data.connectPort,
      method: 'post',
      forbiddenLogo: true
    })
      .then(res => res.workStatus !== STATUS_WORK
        ?
        isCN
          ? message.warn("实验没有运行！")
          : message.warn("Experiment not run!")
        : setPauseMention(true))
      .catch(err => message.error(err));
  }

  //  强制暂停
  function forcePause() {
    setPauseMention(false);
    request({
      url: 'deviceAction/pause',
      data: {
        connectPort: data.connectPort,
        force: true
      },
      method: 'post'
    }).then(res => {
      switch (res.code) {
        case 200:
          dispatch(savePauseCacheTime(Math.floor((Date.now() - startTimeStamp) / 1000) + pauseCacheTime));
          // console.log("时间搓：", startTimeStamp, "缓存时间：", pauseCacheTime, "暂停一共时间", calcMMSS(Math.floor((Date.now() - startTimeStamp) / 1000) + pauseCacheTime));
          break;
        case 500:
          message.error(res.message);
          break;
        default:
          message.error("error");
          // TODO: 排查错误
          console.log(res);
      }
    }).catch(err => message.error(err));
  }

  //  重启实验
  function Restart() {
    request({
      url: 'deviceAction/getStatus',
      data: data.connectPort,
      method: 'post',
      forbiddenLogo: true
    })
      .then(res => {
        if (res.workStatus === STATUS_PAUSE) {
          setRestartMention(true);
        } else {
          isCN
            ? message.warn("实验未暂停或已结束")
            : message.warn("The experiment was not suspended or finished");
        }
      })
      .catch(err => message.error(err));
  }

  //  强制重启
  function forceRestart() {
    setRestartMention(false);
    request({
      url: 'deviceAction/restart',
      data: {
        connectPort: data.connectPort,
        force: true
      },
      method: 'post'
    }).then(res => {
      switch (res.code) {
        case 200:
          console.log(runTime);
          break;
        case 500:
          message.error(res.message);
          break;
        default:
          message.error("error");
          // TODO: 排查错误
          console.log(res);
      }
    }).catch(err => message.error(err));
  }

  function updateProtocolHold(stages) {
    let cloneStages = [];
    cloneStages = deepClone(stages, cloneStages);
    for (let i = 0; i < cloneStages.length; i++) {
      cloneStages[i].index = i;
    }
    //把stages里的hold温度小于15改为15，但前端是多少显示多少
    let holds = cloneStages.filter(item => item.state === HOLD || item.state === INFINITE_HOLD);
    let meltOrAmplification = cloneStages.filter(item => item.state === MELT || item.state === AMPLIFICATION);
    for (let i = 0; i < holds.length; i++) {
      let steps = holds[i].steps[0];
      if (steps.temperature < 15) {
        steps.temperature = 15;
      }
      if (steps.gradientDeltaTemperature.checked) {
        let temp = steps.gradientDeltaTemperature.start;
        steps.gradientDeltaTemperature.start = steps.gradientDeltaTemperature.end;
        steps.gradientDeltaTemperature.end = temp;
      }
    }
    for (let i = 0; i < meltOrAmplification.length; i++) {
      for (let j = 0; j < meltOrAmplification[i].steps.length; j++) {
        let step = meltOrAmplification[i].steps[j];
        if (step.temperature < 15) {
          step.temperature = 15;
        }
        if (step.gradientDeltaTemperature.checked) {
          let temp = step.gradientDeltaTemperature.start;
          step.gradientDeltaTemperature.start = step.gradientDeltaTemperature.end;
          step.gradientDeltaTemperature.end = temp;
        }
      }
    }
    let sort = sortByProperty([...holds, ...meltOrAmplification], 'index');
    return sort.map(item => {
      delete item['index'];
      return item;
    });
  }

  // function updateProtocolHold(stages) {
  //   //把stages里的hold温度小于15改为15，但前端是多少显示多少
  //   console.log('stage',stages);
  //   const handleTemp =(item)=>{
  //     for (let i = 0; i < item.steps.length; i++) {
  //       let steps = item.steps[i];
  //       if (steps.temperature < 15) {
  //         steps.temperature = 15;
  //       }
  //       if (steps.gradientDeltaTemperature.checked) {
  //         let temp = steps.gradientDeltaTemperature.start;
  //         steps.gradientDeltaTemperature.start = steps.gradientDeltaTemperature.end;
  //         steps.gradientDeltaTemperature.end = temp;
  //       }
  //     }
  //   }
  //   let newStage = stages.map(item => {
  //       handleTemp(item)
  //       return item
  //   });
  //   console.log('newStage',newStage);
  //   return newStage;
  // }

  return (
    <div>
      <Header name={isCN ? "实时运行" : "Run"} imgPosition="-150px"/>
      <section className="mainSection pageRun">
        <div className="pageNavigation">
          <ul>
            {
              (isCN ? navContent_CN : navContent).map((item, index) => (
                <Link key={item.content} to={item.path} replace>
                  <li className={"pageNavItem " + (index === navIndex ? "activeNav" : "")}
                      onClick={() => setNavIndex(index)}
                  >
                    {item.content}
                  </li>
                </Link>
              ))
            }
          </ul>
          <ExperimentName/>
        </div>
        <div className="runTime">
          <section>
            <div onClick={start}>{isCN ? "开始" : "Start"}</div>
            <div onClick={stop}>{isCN ? "停止" : "Stop"}</div>
          </section>
          <section>
            <div>
              <div>{startTime}</div>
              <div>{stopTime}</div>
            </div>
            <div className="runTimeCircle">
              <div>
                <Progress type="circle"
                          showInfo={false}
                          percent={runPercent}
                          width={500}
                          gapPosition={"bottom"}
                          strokeColor={"#33BE94"}
                          trailColor={"#ddd"}
                          strokeWidth={15}
                />
              </div>
              <div>
                <div style={{backgroundImage: `url(${openBell ? bell : bellX})`}}
                     onClick={() => openBell ? dispatch(saveOpenBell(false)) : dispatch(saveOpenBell(true))}
                />
                <div>
                  {
                    toggleTime ? "Remain Time" : "Run Time"
                  }
                </div>
                {
                  toggleTime
                    ? <div onClick={() => setToggleTime(false)}>{remainTime}</div>  //  剩余时间
                    : <div onClick={() => setToggleTime(true)}>{runTime}</div>  //  运行时间
                }
              </div>
            </div>
            <div>
              <div id="runTimeTop">{getCurrentHours() + ":" + getCurrentMinutes()}</div>
              <div>{`${getCurrentMonth()} ${getCurrentDay()}, ${getCurrentYear()}`}</div>
            </div>
          </section>
          <section>
            <div onClick={Pause}>{isCN ? "暂停" : "Pause"}</div>
            <div onClick={Restart}>{isCN ? "重新开始" : "Restart"}</div>
          </section>
        </div>
        {
          navIndex === 0
            ? <Status/>
            : <RealtimeCurve/>
        }
      </section>
      {
        stopMention ?
          <Modal
            title=""
            visible={true}
            onOk={forceStop}
            onCancel={() => setStopMention(false)}
          >
            {
              <p
                style={{fontSize: "18px"}}>{isCN ? "你确定要强制终止实验吗?" : "Are you sure you want to force the end of the experiment?"}</p>
            }
          </Modal> : null
      }
      {
        pauseMention ?
          <Modal
            title=""
            visible={true}
            onOk={forcePause}
            onCancel={() => setPauseMention(false)}
          >
            <p
              style={{fontSize: "18px"}}>{isCN ? "你确定要强制暂停实验吗?" : "Are you sure you want to force a suspension?"}</p>
          </Modal> : null
      }
      {
        restartMention ?
          <Modal
            title=""
            visible={true}
            onOk={forceRestart}
            onCancel={() => setRestartMention(false)}
          >
            <p
              style={{fontSize: "18px"}}>{isCN ? "你确定要强制重新开始实验吗 ?" : "Are you sure you want to force a restart?"}</p>
          </Modal> : null
      }
    </div>
  );
});
